<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=2"><meta name="theme-color" content="#222"><meta name="generator" content="Hexo 3.9.0"><link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon.ico"><link rel="icon" type="image/png" sizes="16x16" href="/favicon.ico"><link rel="mask-icon" href="/images/logo.svg" color="#222"><meta name="baidu-site-verification" content="WIIeufYjj6"><link rel="stylesheet" href="/css/main.css"><link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css"><script id="hexo-configurations">var NexT=window.NexT||{},CONFIG={hostname:new URL("http://winddoing.github.io").hostname,root:"/",scheme:"Mist",version:"7.7.0",exturl:!1,sidebar:{position:"right",width:300,display:"post",padding:18,offset:12,onmobile:!1},copycode:{enable:!0,show_result:!1,style:"flat"},back2top:{enable:!0,sidebar:!1,scrollpercent:!1},bookmark:{enable:!1,color:"#222",save:"auto"},fancybox:!1,mediumzoom:!1,lazyload:!1,pangu:!1,comments:{style:"tabs",active:"livere",storage:!0,lazyload:!1,nav:null,activeClass:"livere"},algolia:{appID:"OWFNL0AG1F",apiKey:"796a4b50e2653330cac4e0f8b1f8ade4",indexName:"winddoing",hits:{per_page:10},labels:{input_placeholder:"输入关键词",hits_empty:"没有找到与「${query}」相关的内容",hits_stats:"${hits} 条相关记录，共耗时 ${time} ms"}},localsearch:{enable:!0,trigger:"auto",top_n_per_article:1,unescape:!1,preload:!1},path:"search.xml",motion:{enable:!0,async:!1,transition:{post_block:"fadeIn",post_header:"slideDownIn",post_body:"slideDownIn",coll_header:"slideLeftIn",sidebar:"slideUpIn"}}}</script><meta name="description" content="CGoup核心主要创建一系列sysfs文件，用户空间可以通过这些节点控制CGroup各子系统行为，以及各子系统模块根据参数。在执行过程中或调度进程到不同CPU上，或控制CPU占用时间，或控制IO带宽等等。另外，在每个系统的proc文件系统中都有一个cgroup，显示该进程对应的CGroup各子系统信息。"><meta name="keywords" content="Linux,Cgroup"><meta property="og:type" content="article"><meta property="og:title" content="Cgroup框架的实现"><meta property="og:url" content="http://winddoing.github.io/post/3438.html"><meta property="og:site_name" content="Winddoing&#39;s Blog"><meta property="og:description" content="CGoup核心主要创建一系列sysfs文件，用户空间可以通过这些节点控制CGroup各子系统行为，以及各子系统模块根据参数。在执行过程中或调度进程到不同CPU上，或控制CPU占用时间，或控制IO带宽等等。另外，在每个系统的proc文件系统中都有一个cgroup，显示该进程对应的CGroup各子系统信息。"><meta property="og:locale" content="zh-CN"><meta property="og:image" content="http://winddoing.github.io/images/cgroup/cgroup_struct.png"><meta property="og:image" content="http://winddoing.github.io/images/cgroup/task_cgroup_relation.png"><meta property="og:image" content="http://winddoing.github.io/images/cgroup/cgroup_data_struct.jpeg"><meta property="og:updated_time" content="2020-07-04T09:34:15.248Z"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="Cgroup框架的实现"><meta name="twitter:description" content="CGoup核心主要创建一系列sysfs文件，用户空间可以通过这些节点控制CGroup各子系统行为，以及各子系统模块根据参数。在执行过程中或调度进程到不同CPU上，或控制CPU占用时间，或控制IO带宽等等。另外，在每个系统的proc文件系统中都有一个cgroup，显示该进程对应的CGroup各子系统信息。"><meta name="twitter:image" content="http://winddoing.github.io/images/cgroup/cgroup_struct.png"><link rel="canonical" href="http://winddoing.github.io/post/3438.html"><script id="page-configurations">CONFIG.page={sidebar:"",isHome:!1,isPost:!0}</script><link rel="stylesheet" href="//cdn.jsdelivr.net/gh/theme-next/theme-next-needmoreshare2@1/needsharebutton.min.css"><style>#needsharebutton-postbottom{cursor:pointer;height:26px;margin-top:10px;position:relative}#needsharebutton-postbottom .btn{border:1px solid $btn-default-border-color;border-radius:3px;display:initial;padding:1px 4px}</style><title>Cgroup框架的实现 | Winddoing's Blog</title><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?38fa95924670925239ef842cb0c8722b";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><noscript><style>.sidebar-inner,.use-motion .brand,.use-motion .collection-header,.use-motion .comments,.use-motion .menu-item,.use-motion .pagination,.use-motion .post-block,.use-motion .post-body,.use-motion .post-header{opacity:initial}.use-motion .site-subtitle,.use-motion .site-title{opacity:initial;top:initial}.use-motion .logo-line-before i{left:initial}.use-motion .logo-line-after i{right:initial}</style></noscript></head><body itemscope itemtype="http://schema.org/WebPage"><div class="container use-motion"><div class="headband"></div><header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="header-inner"><div class="site-brand-container"><div class="site-meta"><div><a href="/" class="brand" rel="start"><span class="logo-line-before"><i></i></span> <span class="site-title">Winddoing's Blog</span><span class="logo-line-after"><i></i></span></a></div><h1 class="site-subtitle" itemprop="description">Follow Excellent, Success will Chase you</h1></div><div class="site-nav-toggle"><div class="toggle" aria-label="切换导航栏"><span class="toggle-line toggle-line-first"></span><span class="toggle-line toggle-line-middle"></span><span class="toggle-line toggle-line-last"></span></div></div></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-fw fa-home"></i> 首页</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i> 标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i> 分类</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i> 归档</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-fw fa-user"></i> 关于</a></li><li class="menu-item menu-item-search"><a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i> 搜索</a></li></ul></nav><div class="site-search"><div class="popup search-popup"><div class="search-header"><span class="search-icon"><i class="fa fa-search"></i></span><div class="search-input-container"> <input autocomplete="off" autocorrect="off" autocapitalize="none" placeholder="搜索..." spellcheck="false" type="text" id="search-input"></div><span class="popup-btn-close"><i class="fa fa-times-circle"></i></span></div><div id="search-result"></div></div><div class="search-pop-overlay"></div></div></div></header><div class="back-to-top"><i class="fa fa-arrow-up"></i> <span>0%</span></div><main class="main"><div class="main-inner"><div class="content-wrap"><div class="content"><div class="posts-expand"><article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN"><link itemprop="mainEntityOfPage" href="http://winddoing.github.io/post/3438.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/images/Winddoing.jpg"><meta itemprop="name" content="Winddoing"><meta itemprop="description" content="失败缘于忽视细处，成功始于重视小事。"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Winddoing's Blog"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"> Cgroup框架的实现</h2><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time title="创建时间：2018-03-30 23:07:24" itemprop="dateCreated datePublished" datetime="2018-03-30T23:07:24+08:00">2018-03-30</time></span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Linux内核/" itemprop="url" rel="index"><span itemprop="name">Linux内核</span></a></span></span><span id="/post/3438.html" class="post-meta-item leancloud_visitors" data-flag-title="Cgroup框架的实现" title="阅读次数"><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数：</span><span class="leancloud-visitors-count"></span></span><span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display:none"><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数：</span><span id="busuanzi_value_page_pv"></span></span><br><span class="post-meta-item" title="本文字数"><span class="post-meta-item-icon"><i class="fa fa-file-word-o"></i></span> <span class="post-meta-item-text">本文字数：</span> <span>14k</span></span><span class="post-meta-item" title="阅读时长"><span class="post-meta-item-icon"><i class="fa fa-clock-o"></i></span> <span class="post-meta-item-text">阅读时长 &asymp;</span> <span>13 分钟</span></span></div></header><div class="post-body" itemprop="articleBody"><p>CGoup核心主要创建一系列sysfs文件，用户空间可以通过这些节点控制CGroup各子系统行为，以及各子系统模块根据参数。在执行过程中或调度进程到不同CPU上，或控制CPU占用时间，或控制IO带宽等等。另外，在每个系统的proc文件系统中都有一个cgroup，显示该进程对应的CGroup各子系统信息。</p><p><img src="/images/cgroup/cgroup_struct.png" alt="cgroup strutc"></p><a id="more"></a><h2 id="内核配置"><a href="#内核配置" class="headerlink" title="内核配置"></a>内核配置</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">Symbol: CGROUPS [=y]</span><br><span class="line">Type  : boolean</span><br><span class="line">Prompt: Control Group support</span><br><span class="line">  Location:</span><br><span class="line">      -&gt; General setup</span><br><span class="line"></span><br><span class="line">Symbol: CGROUP_SCHED [=y]</span><br><span class="line">Type  : boolean</span><br><span class="line">Prompt: Group CPU scheduler</span><br><span class="line">  Location:</span><br><span class="line">      -&gt; General setup</span><br><span class="line">	        -&gt; Control Group support (CGROUPS [=y])</span><br></pre></td></tr></table></figure><p>通过<code>CONFIG_CGROUPS</code>配置cgroup框架的实现,<code>CONFIG_CGROUP_SCHED</code>控制CPU子系统。</p><h2 id="基本应用"><a href="#基本应用" class="headerlink" title="基本应用"></a>基本应用</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> mount -t cgroup -o cpu cgroup /mnt/</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> mkdir tst_cgroup</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> rmdir tst_cgroup</span></span><br></pre></td></tr></table></figure><p>在文件系统中cgroup的挂载目录,也就是cgroup虚拟文件系统的根目录用数据结构<code>struct cgroupfs_root</code>表示.而cgroup用<code>struct cgroup</code>表示.</p><h2 id="数据结构"><a href="#数据结构" class="headerlink" title="数据结构"></a>数据结构</h2><p>主要用于对进程不同资源的管理和配置，以及进程和cgroup之间的关系。</p><h3 id="task-struct"><a href="#task-struct" class="headerlink" title="task_struct"></a>task_struct</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">task_struct</span> &#123;</span></span><br><span class="line">    ...</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> CONFIG_CGROUPS</span></span><br><span class="line">	<span class="comment">/* Control Group info protected by css_set_lock */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">css_set</span> __<span class="title">rcu</span> *<span class="title">cgroups</span>;</span></span><br><span class="line">	<span class="comment">/* cg_list protected by css_set_lock and tsk-&gt;alloc_lock */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">cg_list</span>;</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">    ...</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p><code>struct task_struct</code>中并没有一个直接的成员指向cgroup,而是指向了<code>struct css_set</code>的结构, css_set存储路与进程相关的cgroup信息。</p><p><code>cg_list</code>: 是一个链表结构，用于将连到同一个css_set的进程组织成一个链表。</p><h3 id="css-set"><a href="#css-set" class="headerlink" title="css_set"></a>css_set</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * A css_set is a structure holding pointers to a set of</span></span><br><span class="line"><span class="comment"> * cgroup_subsys_state objects. This saves space in the task struct</span></span><br><span class="line"><span class="comment"> * object and speeds up fork()/exit(), since a single inc/dec and a</span></span><br><span class="line"><span class="comment"> * list_add()/del() can bump the reference count on the entire cgroup</span></span><br><span class="line"><span class="comment"> * set for a task.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">css_set</span> &#123;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Reference count */</span></span><br><span class="line">	<span class="keyword">atomic_t</span> refcount;  <span class="comment">//引用计数，因为一个css_set可以被多个进程共用，这些进程的cgroup信息相同</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * List running through all cgroup groups in the same hash</span></span><br><span class="line"><span class="comment">	 * slot. Protected by css_set_lock</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">hlist_node</span> <span class="title">hlist</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * List running through all tasks using this cgroup</span></span><br><span class="line"><span class="comment">	 * group. Protected by css_set_lock</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">tasks</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * List of cg_cgroup_link objects on link chains from</span></span><br><span class="line"><span class="comment">	 * cgroups referenced from this css_set. Protected by</span></span><br><span class="line"><span class="comment">	 * css_set_lock</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">     <span class="comment">//由cg_cgroup_link组成的链表，链表上每一项cg_cgroup_link都指向和css_set关联的cgroup.</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">cg_links</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * Set of subsystem states, one for each subsystem. This array</span></span><br><span class="line"><span class="comment">	 * is immutable after creation apart from the init_css_set</span></span><br><span class="line"><span class="comment">	 * during subsystem registration (at boot time) and modular subsystem</span></span><br><span class="line"><span class="comment">	 * loading/unloading.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">     <span class="comment">/*</span></span><br><span class="line"><span class="comment">     *css_set关联的css.每一个subsystem对应数组中相应id的项。</span></span><br><span class="line"><span class="comment">     *subsys应当包括所有子系统的css.如果此css_set没有制定某个subsystem的css或者subsystem没有mount，则默认初始化为根css.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">cgroup_subsys_state</span> *<span class="title">subsys</span>[<span class="title">CGROUP_SUBSYS_COUNT</span>];</span> <span class="comment">//是进程与一个特定子系统相关的信息</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* For RCU-protected deletion */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">rcu_head</span> <span class="title">rcu_head</span>;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><blockquote><p>file: include/linux/cgroup.h</p></blockquote><p>主要用来描述一个个子系统，通过<code>cgroup_subsys_state</code>定义不同子系统的相关控制信息，<code>hlist</code>将同一个子系统下的所有css_set组织成一个hash表，方便内核查找特定的css_set.<br><code>tasks</code>指向所有连到此css_set的进程连成的链表。</p><p>那从<code>struct css_set</code>怎么转换到cgroup呢? 再来看一个辅助的数据结构<code>struct cg_cgroup_link</code></p><h3 id="cgroup-subsys-state"><a href="#cgroup-subsys-state" class="headerlink" title="cgroup_subsys_state"></a>cgroup_subsys_state</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Per-subsystem/per-cgroup state maintained by the system. */</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">cgroup_subsys_state</span> &#123;</span></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * The cgroup that this subsystem is attached to. Useful</span></span><br><span class="line"><span class="comment">     * for subsystems that want to know about the cgroup</span></span><br><span class="line"><span class="comment">     * hierarchy structure</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">cgroup</span> *<span class="title">cgroup</span>;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * State maintained by the cgroup system to allow subsystems</span></span><br><span class="line"><span class="comment">     * to be "busy". Should be accessed via css_get(),</span></span><br><span class="line"><span class="comment">     * css_tryget() and css_put().</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">atomic_t</span> refcnt;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">long</span> flags;</span><br><span class="line">    <span class="comment">/* ID for this css, if possible */</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">css_id</span> __<span class="title">rcu</span> *<span class="title">id</span>;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/* Used to put @cgroup-&gt;dentry on the last css_put() */</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">work_struct</span> <span class="title">dput_work</span>;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><blockquote><p>file: include/linux/cgroup.h</p></blockquote><p>cgroup指针指向了一个cgroup结构，也就是进程属于的cgroup.</p><p>进程受到子系统的控制，实际上是通过加入到特定的cgroup实现的，因为cgroup在特定的层级上，而子系统又是附加到曾经上的 。通过以上三个结构，进程就可以和cgroup关联起来了 ：</p><blockquote><p>task_struct-&gt;css_set-&gt;cgroup_subsys_state-&gt;cgroup。</p></blockquote><p><img src="/images/cgroup/task_cgroup_relation.png" alt="task cgroup"></p><h3 id="cgroup"><a href="#cgroup" class="headerlink" title="cgroup"></a>cgroup</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">cgroup</span> &#123;</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> flags;		<span class="comment">/* "unsigned long" so bitops work */</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * count users of this cgroup. &gt;0 means busy, but doesn't</span></span><br><span class="line"><span class="comment">	 * necessarily indicate the number of tasks in the cgroup</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="keyword">atomic_t</span> count;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">int</span> id;				<span class="comment">/* ida allocated in-hierarchy ID */</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * We link our 'sibling' struct into our parent's 'children'.</span></span><br><span class="line"><span class="comment">	 * Our children link their 'sibling' into our 'children'.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">sibling</span>;</span>	<span class="comment">/* my parent's children */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">children</span>;</span>	<span class="comment">/* my children */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">files</span>;</span>		<span class="comment">/* my files */</span></span><br><span class="line"></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">cgroup</span> *<span class="title">parent</span>;</span>		<span class="comment">/* my parent */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">dentry</span> *<span class="title">dentry</span>;</span>		<span class="comment">/* cgroup fs entry, RCU protected */</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * This is a copy of dentry-&gt;d_name, and it's needed because</span></span><br><span class="line"><span class="comment">	 * we can't use dentry-&gt;d_name in cgroup_path().</span></span><br><span class="line"><span class="comment">	 *</span></span><br><span class="line"><span class="comment">	 * You must acquire rcu_read_lock() to access cgrp-&gt;name, and</span></span><br><span class="line"><span class="comment">	 * the only place that can change it is rename(), which is</span></span><br><span class="line"><span class="comment">	 * protected by parent dir's i_mutex.</span></span><br><span class="line"><span class="comment">	 *</span></span><br><span class="line"><span class="comment">	 * Normally you should use cgroup_name() wrapper rather than</span></span><br><span class="line"><span class="comment">	 * access it directly.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">cgroup_name</span> __<span class="title">rcu</span> *<span class="title">name</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Private pointers for each registered subsystem */</span></span><br><span class="line">    <span class="comment">//此cgroup关联subsystem的css结构，每个subsystem的css在数组中对应subsys[subsystem-&gt;subsys_id].</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">cgroup_subsys_state</span> *<span class="title">subsys</span>[<span class="title">CGROUP_SUBSYS_COUNT</span>];</span></span><br><span class="line"></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">cgroupfs_root</span> *<span class="title">root</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * List of cg_cgroup_links pointing at css_sets with</span></span><br><span class="line"><span class="comment">	 * tasks in this cgroup. Protected by css_set_lock</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">css_sets</span>;</span> <span class="comment">//通过cs_cgroup_link指向此cgroup关联的css_set</span></span><br><span class="line"></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">allcg_node</span>;</span>	<span class="comment">/* cgroupfs_root-&gt;allcg_list */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">cft_q_node</span>;</span>	<span class="comment">/* used during cftype add/rm */</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * Linked list running through all cgroups that can</span></span><br><span class="line"><span class="comment">	 * potentially be reaped by the release agent. Protected by</span></span><br><span class="line"><span class="comment">	 * release_list_lock</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">release_list</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * list of pidlists, up to two for each namespace (one for procs, one</span></span><br><span class="line"><span class="comment">	 * for tasks); created on demand.</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">pidlists</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">mutex</span> <span class="title">pidlist_mutex</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* For RCU-protected deletion */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">rcu_head</span> <span class="title">rcu_head</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">work_struct</span> <span class="title">free_work</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* List of events which userspace want to receive */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">event_list</span>;</span></span><br><span class="line">	<span class="keyword">spinlock_t</span> event_list_lock;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* directory xattrs */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">simple_xattrs</span> <span class="title">xattrs</span>;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><ul><li><code>sibling</code>,<code>children</code>和<code>parent</code>三个list_head负责将同一层级的cgroup连接成一颗cgroup树。</li><li><code>subsys</code>是一个指针数组，存储一组指向cgroup_subsys_state的指针。这组指针指向了此cgroup跟各个子系统相关的信息</li><li><code>root</code>指向了一个cgroupfs_root的结构，就是cgroup所在的层级对应的结构体</li></ul><p>cgroup和css_set是多对多的关系，既：一个css_set可以对应多个cgroup,同时一个cgroup也可以被多个css_set所包含。<br>这种多对多的映射关系，是通过cg_cgroup_link这个中间结构来关联的。</p><h3 id="cg-cgroup-link"><a href="#cg-cgroup-link" class="headerlink" title="cg_cgroup_link"></a>cg_cgroup_link</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Link structure for associating css_set objects with cgroups */</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">cg_cgroup_link</span> &#123;</span></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * List running through cg_cgroup_links associated with a</span></span><br><span class="line"><span class="comment">     * cgroup, anchored on cgroup-&gt;css_sets</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">cgrp_link_list</span>;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">cgroup</span> *<span class="title">cgrp</span>;</span></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * List running through cg_cgroup_links pointing at a</span></span><br><span class="line"><span class="comment">     * single css_set object, anchored on css_set-&gt;cg_links</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">cg_link_list</span>;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">css_set</span> *<span class="title">cg</span>;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>一个cg_cgroup_link需要包含两类信息，即关联的cgroup和css_set信息，一个cg_cgroup_link可以让一个cgroup和一个css_set相关联。但是正如我们前面所说，css_set和cgroup是多对多的对应关系，所以，一个css_set需要保存多个cg_cgroup_link，一个cgroup也需要保存多个cg_cgroup_link信息。具体来说，css_set中的cg_links维护了一个链表，链表中的元素为cg_cgroup_link中的cg_link_list.cgroup中的css_set也维护了一个cg_cgroup_link链表，链表中元素为cgrp_link_list.</p><p><code>cgrp_link_list</code>连入到<code>cgroup-&gt;css_set</code>指向的链表，cgrp则指向此<code>cg_cgroup_link</code>相关的cgroup。</p><p><code>cg_link_list</code>则连入到<code>css_set-&gt;cg_links</code>指向的链表,cg则指向此<code>cg_cgroup_link</code>相关的css_set。</p><h3 id="cgroupfs-root"><a href="#cgroupfs-root" class="headerlink" title="cgroupfs_root"></a>cgroupfs_root</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * A cgroupfs_root represents the root of a cgroup hierarchy, and may be</span></span><br><span class="line"><span class="comment"> * associated with a superblock to form an active hierarchy.  This is</span></span><br><span class="line"><span class="comment"> * internal to cgroup core.  Don't access directly from controllers.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">cgroupfs_root</span> &#123;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">super_block</span> *<span class="title">sb</span>;</span>  <span class="comment">//cgroup文件系统的超级块</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * The bitmask of subsystems intended to be attached to this</span></span><br><span class="line"><span class="comment">	 * hierarchy</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> subsys_mask; <span class="comment">//hierarchy相关联的subsys 位图</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Unique id for this hierarchy. */</span></span><br><span class="line">	<span class="keyword">int</span> hierarchy_id;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* The bitmask of subsystems currently attached to this hierarchy */</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> actual_subsys_mask;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* A list running through the attached subsystems */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">subsys_list</span>;</span> <span class="comment">//hierarchy中的subsys链表</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* The root cgroup for this hierarchy */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">cgroup</span> <span class="title">top_cgroup</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Tracks how many cgroups are currently defined in hierarchy.*/</span></span><br><span class="line">	<span class="keyword">int</span> number_of_cgroups;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* A list running through the active hierarchies */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">root_list</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* All cgroups on this root, cgroup_mutex protected */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">allcg_list</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Hierarchy-specific flags */</span></span><br><span class="line">	<span class="keyword">unsigned</span> <span class="keyword">long</span> flags;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* IDs for cgroups in this hierarchy */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">ida</span> <span class="title">cgroup_ida</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="comment">/* The path to use for release notifications. */</span></span><br><span class="line">	<span class="keyword">char</span> release_agent_path[PATH_MAX];</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* The name for this hierarchy - may be empty */</span></span><br><span class="line">	<span class="keyword">char</span> name[MAX_CGROUP_ROOT_NAMELEN];</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p><code>top_cgroup</code>指向了所在层级的根cgroup，也就是创建层级时自动创建的那个cgroup。</p><h3 id="cgroup-subsys"><a href="#cgroup-subsys" class="headerlink" title="cgroup_subsys"></a>cgroup_subsys</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Control Group subsystem type.</span></span><br><span class="line"><span class="comment"> * See Documentation/cgroups/cgroups.txt for details</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">cgroup_subsys</span> &#123;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">cgroup_subsys_state</span> *(*<span class="title">css_alloc</span>)(<span class="title">struct</span> <span class="title">cgroup</span> *<span class="title">cgrp</span>);</span></span><br><span class="line">    <span class="keyword">int</span> (*css_online)(struct cgroup *cgrp);</span><br><span class="line">    <span class="keyword">void</span> (*css_offline)(struct cgroup *cgrp);</span><br><span class="line">    <span class="keyword">void</span> (*css_free)(struct cgroup *cgrp);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> (*allow_attach)(struct cgroup *cgrp, struct cgroup_taskset *tset);</span><br><span class="line">    <span class="keyword">int</span> (*can_attach)(struct cgroup *cgrp, struct cgroup_taskset *tset);</span><br><span class="line">    <span class="keyword">void</span> (*cancel_attach)(struct cgroup *cgrp, struct cgroup_taskset *tset);</span><br><span class="line">    <span class="keyword">void</span> (*<span class="built_in">attach</span>)(struct cgroup *cgrp, struct cgroup_taskset *tset);</span><br><span class="line">    <span class="keyword">void</span> (*fork)(struct task_struct *task);</span><br><span class="line">    <span class="keyword">void</span> (*<span class="built_in">exit</span>)(struct cgroup *cgrp, struct cgroup *old_cgrp,</span><br><span class="line">             struct task_struct *task);</span><br><span class="line">    <span class="keyword">void</span> (*bind)(struct cgroup *root);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> subsys_id;</span><br><span class="line">    <span class="keyword">int</span> disabled;</span><br><span class="line">    <span class="keyword">int</span> early_init;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * True if this subsys uses ID. ID is not available before cgroup_init()</span></span><br><span class="line"><span class="comment">     * (not available in early_init time.)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">bool</span> use_id;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * If %false, this subsystem is properly hierarchical -</span></span><br><span class="line"><span class="comment">     * configuration, resource accounting and restriction on a parent</span></span><br><span class="line"><span class="comment">     * cgroup cover those of its children.  If %true, hierarchy support</span></span><br><span class="line"><span class="comment">     * is broken in some ways - some subsystems ignore hierarchy</span></span><br><span class="line"><span class="comment">     * completely while others are only implemented half-way.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * It's now disallowed to create nested cgroups if the subsystem is</span></span><br><span class="line"><span class="comment">     * broken and cgroup core will emit a warning message on such</span></span><br><span class="line"><span class="comment">     * cases.  Eventually, all subsystems will be made properly</span></span><br><span class="line"><span class="comment">     * hierarchical and this will go away.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"></span><br><span class="line">     <span class="keyword">bool</span> broken_hierarchy;</span><br><span class="line">     <span class="keyword">bool</span> warned_broken_hierarchy;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAX_CGROUP_TYPE_NAMELEN 32</span></span><br><span class="line">     <span class="keyword">const</span> <span class="keyword">char</span> *name;</span><br><span class="line"></span><br><span class="line">     <span class="comment">/*</span></span><br><span class="line"><span class="comment">      * Link to parent, and list entry in parent's children.</span></span><br><span class="line"><span class="comment">      * Protected by cgroup_lock()</span></span><br><span class="line"><span class="comment">      */</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span> <span class="title">cgroupfs_root</span> *<span class="title">root</span>;</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">sibling</span>;</span></span><br><span class="line">     <span class="comment">/* used when use_id == true */</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span> <span class="title">idr</span> <span class="title">idr</span>;</span></span><br><span class="line">     <span class="keyword">spinlock_t</span> id_lock;</span><br><span class="line"></span><br><span class="line">     <span class="comment">/* list of cftype_sets */</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">cftsets</span>;</span></span><br><span class="line"></span><br><span class="line">     <span class="comment">/* base cftypes, automatically [de]registered with subsys itself */</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span> <span class="title">cftype</span> *<span class="title">base_cftypes</span>;</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span> <span class="title">cftype_set</span> <span class="title">base_cftset</span>;</span></span><br><span class="line"></span><br><span class="line">     <span class="comment">/* should be defined only by modular subsystems */</span></span><br><span class="line">     <span class="class"><span class="keyword">struct</span> <span class="title">module</span> *<span class="title">module</span>;</span></span><br><span class="line"> &#125;;</span><br></pre></td></tr></table></figure><p>Cgroup_subsys定义了一组操作，让各个子系统根据各自的需要去实现。这个相当于C++中抽象基类，然后各个特定的子系统对应cgroup_subsys则是实现了相应操作的子类。类似的思想还被用在了cgroup_subsys_state中，cgroup_subsys_state并未定义控制信息，而只是定义了各个子系统都需要的共同信息，比如该cgroup_subsys_state从属的cgroup。然后各个子系统再根据各自的需要去定义自己的进程控制信息结构体，最后在各自的结构体中将cgroup_subsys_state包含进去，这样通过Linux内核的container_of等宏就可以通过cgroup_subsys_state来获取相应的结构体。</p><h3 id="联系"><a href="#联系" class="headerlink" title="联系"></a>联系</h3><p><img src="/images/cgroup/cgroup_data_struct.jpeg" alt="cgroup data struct"></p><table><thead><tr><th style="text-align:center">数据结构</th><th style="text-align:center">划分</th></tr></thead><tbody><tr><td style="text-align:center">cgroupfs_root</td><td style="text-align:center">层级（hierarchy）</td></tr><tr><td style="text-align:center">css_set</td><td style="text-align:center">子系统（subsystem）</td></tr><tr><td style="text-align:center">cgroup</td><td style="text-align:center">进程控制组</td></tr></tbody></table><h2 id="cgroup初始化"><a href="#cgroup初始化" class="headerlink" title="cgroup初始化"></a>cgroup初始化</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">start_kernel</span><br><span class="line">	\-&gt;cgroup_init_early();</span><br><span class="line">		\-&gt;init_cgroup_root</span><br><span class="line">		\-&gt;cgroup_init_subsys</span><br><span class="line">	\-&gt;cgroup_init();</span><br><span class="line">		\-&gt;cgroup_init_subsys</span><br><span class="line">		\-&gt;kobject_create_and_add</span><br><span class="line">		\-&gt;register_filesystem</span><br></pre></td></tr></table></figure><h3 id="cgroup-init-early"><a href="#cgroup-init-early" class="headerlink" title="cgroup_init_early"></a>cgroup_init_early</h3><p>第一阶段：主要进行数据结构的初始化和链表之间关系的绑定</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> __<span class="function">init <span class="title">cgroup_init_early</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    atomic_set(&amp;init_css_set.refcount, <span class="number">1</span>);</span><br><span class="line">    INIT_LIST_HEAD(&amp;init_css_set.cg_links); <span class="comment">//初始化全局结构体struct css_set init</span></span><br><span class="line">    INIT_LIST_HEAD(&amp;init_css_set.tasks);</span><br><span class="line">    INIT_HLIST_NODE(&amp;init_css_set.hlist);</span><br><span class="line">    css_set_count = <span class="number">1</span>;  <span class="comment">//系统中struct css_set计数</span></span><br><span class="line">    init_cgroup_root(&amp;rootnode); <span class="comment">//初始化全局结构体struct cgroupfs_root</span></span><br><span class="line">    root_count = <span class="number">1</span>;		<span class="comment">//系统中的层级计数</span></span><br><span class="line">    init_task.cgroups = &amp;init_css_set; <span class="comment">//使系统的初始化进程cgroup指向init_css_set</span></span><br><span class="line"></span><br><span class="line">    init_css_set_link.cg = &amp;init_css_set;</span><br><span class="line">	<span class="comment">/* dummytop is a shorthand for the dummy hierarchy's top cgroup */</span></span><br><span class="line">    init_css_set_link.cgrp = dummytop;</span><br><span class="line"></span><br><span class="line">    list_add(&amp;init_css_set_link.cgrp_link_list,</span><br><span class="line">         &amp;rootnode.top_cgroup.css_sets);</span><br><span class="line">    list_add(&amp;init_css_set_link.cg_link_list,</span><br><span class="line">         &amp;init_css_set.cg_links);</span><br><span class="line"></span><br><span class="line">	<span class="comment">//对一些需要在系统启动时初始化的subsys进行初始化</span></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; CGROUP_SUBSYS_COUNT; i++) &#123;</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">cgroup_subsys</span> *<span class="title">ss</span> = <span class="title">subsys</span>[<span class="title">i</span>];</span></span><br><span class="line"></span><br><span class="line">		...</span><br><span class="line">        <span class="keyword">if</span> (ss-&gt;early_init)</span><br><span class="line">            cgroup_init_subsys(ss);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="cgroup-init"><a href="#cgroup-init" class="headerlink" title="cgroup_init"></a>cgroup_init</h3><p>第二阶段： 主要生成cgroup虚拟文件系统</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * cgroup_init - cgroup initialization</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * Register cgroup filesystem and /proc file, and initialize</span></span><br><span class="line"><span class="comment"> * any subsystems that didn't request early init.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> __<span class="function">init <span class="title">cgroup_init</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	...</span><br><span class="line">    err = bdi_init(&amp;cgroup_backing_dev_info);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; CGROUP_SUBSYS_COUNT; i++) &#123;</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">cgroup_subsys</span> *<span class="title">ss</span> = <span class="title">subsys</span>[<span class="title">i</span>];</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">/* at bootup time, we don't worry about modular subsystems */</span></span><br><span class="line">        <span class="keyword">if</span> (!ss || ss-&gt;<span class="keyword">module</span>)</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        <span class="keyword">if</span> (!ss-&gt;early_init)</span><br><span class="line">            cgroup_init_subsys(ss);</span><br><span class="line">        <span class="keyword">if</span> (ss-&gt;use_id)</span><br><span class="line">            cgroup_init_idr(ss, init_css_set.subsys[ss-&gt;subsys_id]);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* Add init_css_set to the hash table */</span></span><br><span class="line">    key = css_set_hash(init_css_set.subsys);</span><br><span class="line">    hash_add(css_set_table, &amp;init_css_set.hlist, key);</span><br><span class="line">    BUG_ON(!init_root_id(&amp;rootnode));</span><br><span class="line">	...</span><br><span class="line">    cgroup_kobj = kobject_create_and_add(<span class="string">"cgroup"</span>, fs_kobj);</span><br><span class="line"></span><br><span class="line">    err = register_filesystem(&amp;cgroup_fs_type);</span><br><span class="line"></span><br><span class="line">    proc_create(<span class="string">"cgroups"</span>, <span class="number">0</span>, <span class="literal">NULL</span>, &amp;proc_cgroupstats_operations);</span><br><span class="line">	...</span><br><span class="line">    <span class="keyword">return</span> err;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>1.bdi_init用于初始化后备存储器的一些字段，这些字段包括回写链表、回写锁等，关系到读写策略，和挂载关系并不大</p><h3 id="subsys"><a href="#subsys" class="headerlink" title="subsys"></a>subsys</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> SUBSYS(_x) [_x ## _subsys_id] = &amp;_x ## _subsys,</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)</span></span><br><span class="line"><span class="keyword">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">cgroup_subsys</span> *<span class="title">subsys</span>[<span class="title">CGROUP_SUBSYS_COUNT</span>] = &#123;</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;linux/cgroup_subsys.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> IS_SUBSYS_ENABLED(CONFIG_CGROUP_DEBUG)</span></span><br><span class="line">SUBSYS(debug)</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><blockquote><p>file: kernel/cgroup.c</p></blockquote><h2 id="cgroup文件系统的挂载"><a href="#cgroup文件系统的挂载" class="headerlink" title="cgroup文件系统的挂载"></a>cgroup文件系统的挂载</h2><blockquote><p>mount -t cgroup -o cpu cgroup /mnt/</p></blockquote><h3 id="注册："><a href="#注册：" class="headerlink" title="注册："></a>注册：</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">file_system_type</span> <span class="title">cgroup_fs_type</span> = &#123;</span></span><br><span class="line">	.name = <span class="string">"cgroup"</span>,</span><br><span class="line">	.mount = cgroup_mount,</span><br><span class="line">	.kill_sb = cgroup_kill_sb,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><h3 id="调用关系："><a href="#调用关系：" class="headerlink" title="调用关系："></a>调用关系：</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">SyS_mount</span><br><span class="line">	\-&gt;do_mount</span><br><span class="line">		\-&gt;vfs_kern_mount</span><br><span class="line">			\-&gt;mount_fs</span><br><span class="line">				\-&gt;cgroup_mount</span><br><span class="line">					\-&gt;cgroup_populate_dir  //生成基础的文件属性</span><br></pre></td></tr></table></figure><p>cgoup基础的文件：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*for hysterical raisins, we can't put this on the older files*/</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> CGROUP_FILE_GENERIC_PREFIX <span class="meta-string">"cgroup."</span></span></span><br><span class="line"><span class="keyword">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">cftype</span> <span class="title">files</span>[] = &#123;</span></span><br><span class="line">    &#123;</span><br><span class="line">        .name = <span class="string">"tasks"</span>,</span><br><span class="line">        .<span class="built_in">open</span> = cgroup_tasks_open,</span><br><span class="line">        .write_u64 = cgroup_tasks_write,</span><br><span class="line">        .<span class="built_in">release</span> = cgroup_pidlist_release,</span><br><span class="line">        .mode = S_IRUGO | S_IWUSR,</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        .name = CGROUP_FILE_GENERIC_PREFIX <span class="string">"procs"</span>,</span><br><span class="line">        .<span class="built_in">open</span> = cgroup_procs_open,</span><br><span class="line">        .write_u64 = cgroup_procs_write,</span><br><span class="line">        .<span class="built_in">release</span> = cgroup_pidlist_release,</span><br><span class="line">        .mode = S_IRUGO | S_IWUSR,</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        .name = <span class="string">"notify_on_release"</span>,</span><br><span class="line">        .read_u64 = cgroup_read_notify_on_release,</span><br><span class="line">        .write_u64 = cgroup_write_notify_on_release,</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        .name = CGROUP_FILE_GENERIC_PREFIX <span class="string">"event_control"</span>,</span><br><span class="line">        .write_string = cgroup_write_event_control,</span><br><span class="line">        .mode = S_IWUGO,</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        .name = <span class="string">"cgroup.clone_children"</span>,</span><br><span class="line">        .flags = CFTYPE_INSANE,</span><br><span class="line">        .read_u64 = cgroup_clone_children_read,</span><br><span class="line">        .write_u64 = cgroup_clone_children_write,</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        .name = <span class="string">"cgroup.sane_behavior"</span>,</span><br><span class="line">        .flags = CFTYPE_ONLY_ON_ROOT,</span><br><span class="line">        .read_seq_string = cgroup_sane_behavior_show,</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        .name = <span class="string">"release_agent"</span>,</span><br><span class="line">        .flags = CFTYPE_ONLY_ON_ROOT,</span><br><span class="line">        .read_seq_string = cgroup_release_agent_show,</span><br><span class="line">        .write_string = cgroup_release_agent_write,</span><br><span class="line">        .max_write_len = PATH_MAX,</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123; &#125; <span class="comment">/* terminate */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><h2 id="创建子cgroup"><a href="#创建子cgroup" class="headerlink" title="创建子cgroup"></a>创建子cgroup</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">SyS_mkdirat</span><br><span class="line">	\-&gt;cgroup_mkdir</span><br><span class="line">		\-&gt;cgroup_create</span><br></pre></td></tr></table></figure><h2 id="task"><a href="#task" class="headerlink" title="task"></a>task</h2><blockquote><p>echo $$ &gt; task</p></blockquote><p>将当前进程迁移到一个cgroup中：</p><p>Open:<br></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">do_sys_open</span><br><span class="line"> |-&gt;do_filp_open</span><br><span class="line">   |-&gt; path_openat.isra.13</span><br><span class="line">     |-&gt;do_last.isra.12</span><br><span class="line">       |-&gt;finish_open</span><br><span class="line">         |-&gt;do_dentry_open.isra.2</span><br><span class="line">		   |-&gt;cgroup_pidlist_open</span><br></pre></td></tr></table></figure><p></p><p>Write:<br></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">SyS_write</span><br><span class="line">  |-&gt;vfs_write</span><br><span class="line">    |-&gt;cgroup_file_write</span><br><span class="line">      |-&gt;cgroup_tasks_write</span><br><span class="line">        |-&gt;attach_task_by_pid</span><br></pre></td></tr></table></figure><p></p><h2 id="DEBUG子系统实现"><a href="#DEBUG子系统实现" class="headerlink" title="DEBUG子系统实现"></a>DEBUG子系统实现</h2><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">cgroup_subsys</span> <span class="title">debug_subsys</span> = &#123;</span></span><br><span class="line">    .name = <span class="string">"debug"</span>,</span><br><span class="line">    .css_alloc = debug_css_alloc,</span><br><span class="line">    .css_free = debug_css_free,</span><br><span class="line">    .subsys_id = debug_subsys_id,</span><br><span class="line">    .base_cftypes = debug_files,</span><br><span class="line">&#125;;                                           SS</span><br></pre></td></tr></table></figure><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ol><li><a href="https://files.cnblogs.com/files/lisperl/cgroups%E4%BB%8B%E7%BB%8D.pdf" target="_blank" rel="noopener">Linux Cgroups 详解</a></li><li><a href="https://blog.csdn.net/zhangyifei216/article/details/49491549" target="_blank" rel="noopener">Cgroup框架分析</a></li><li><a href="http://www.xuebuyuan.com/624249.html" target="_blank" rel="noopener">Linux cgroup机制分析之框架分析</a></li><li><a href="http://www.cnblogs.com/arnoldlu/p/6208443.html" target="_blank" rel="noopener">Android/Linux下CGroup框架分析及其使用</a></li></ol></div><div class="popular-posts-header">相关文章</div><ul class="popular-posts"><li class="popular-posts-item"><div class="popular-posts-title"><a href="/post/10807.html" rel="bookmark">Cgroup</a></div></li><li class="popular-posts-item"><div class="popular-posts-title"><a href="/post/36419.html" rel="bookmark">Cortex-A8平台实验</a></div></li><li class="popular-posts-item"><div class="popular-posts-title"><a href="/post/57226.html" rel="bookmark">内核常见问题</a></div></li><li class="popular-posts-item"><div class="popular-posts-title"><a href="/post/23122.html" rel="bookmark">setup_per_cpu_areas</a></div></li><li class="popular-posts-item"><div class="popular-posts-title"><a href="/post/42371.html" rel="bookmark">Linux内核同步机制【rwlock】</a></div></li></ul><div class="post-widgets"><div id="needsharebutton-postbottom"><span class="btn"><i class="fa fa-share-alt" aria-hidden="true"></i></span></div></div><div><div style="text-align:center;color:#ccc;font-size:14px">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div><div style="text-align:center;color:#ccc;font-size:16px"><script type="text/javascript" src="https://api.imjad.cn/hitokoto/?cat=&charset=utf-8&length=50&encode=js&fun=sync&source="></script><div id="hitokoto"><script>hitokoto()</script></div></div><div class="reward-container"><div></div> <button disable="enable" onclick="var qr = document.getElementById(&quot;qr&quot;); qr.style.display = (qr.style.display === 'none') ? 'block' : 'none';"> 打赏</button><div id="qr" style="display:none"><div style="display:inline-block"> <img src="/images/alipay.jpg" alt="Winddoing 支付宝"><p>支付宝</p></div></div></div><div><ul class="post-copyright"><li class="post-copyright-author"> <strong>本文作者：</strong> Winddoing</li><li class="post-copyright-link"> <strong>本文链接：</strong> <a href="http://winddoing.github.io/post/3438.html" title="Cgroup框架的实现">http://winddoing.github.io/post/3438.html</a></li><li class="post-copyright-statement"> <strong>作者声明：</strong> 本博文为个人笔记, 由于个人能力有限，难免出现错误，欢迎大家批评指正。</li><li class="post-copyright-license"> <strong>版权声明：</strong> 本博客所有文章除特别声明外，均采用<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fa fa-fw fa-creative-commons"></i> BY-NC-SA</a> 许可协议。转载请注明出处！</li></ul></div><footer class="post-footer"><div class="post-tags"><a href="/tags/Linux/" rel="tag"><i class="fa fa-tag"></i> Linux</a><a href="/tags/Cgroup/" rel="tag"><i class="fa fa-tag"></i> Cgroup</a></div><div class="post-nav"><div class="post-nav-item"><a href="/post/62201.html" rel="prev" title="Linux内核同步机制【spin lock】"><i class="fa fa-chevron-left"></i> Linux内核同步机制【spin lock】</a></div><div class="post-nav-item"> <a href="/post/14105.html" rel="next" title="GCC编译器的优化： fprefetch-loop-arrays">GCC编译器的优化： fprefetch-loop-arrays<i class="fa fa-chevron-right"></i></a></div></div></footer></div></article></div></div><div class="comments"><div id="lv-container" data-id="city" data-uid="MTAyMC8yOTM5OC81OTY2"></div></div><script>
  window.addEventListener('tabs:register', () => {
    let activeClass = CONFIG.comments.activeClass;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script></div><div class="toggle sidebar-toggle"><span class="toggle-line toggle-line-first"></span><span class="toggle-line toggle-line-middle"></span><span class="toggle-line toggle-line-last"></span></div><aside class="sidebar"><div class="sidebar-inner"><ul class="sidebar-nav motion-element"><li class="sidebar-nav-toc"> 文章目录</li><li class="sidebar-nav-overview"> 站点概览</li></ul><div class="post-toc-wrap sidebar-panel"><div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#内核配置"><span class="nav-number">1.</span> <span class="nav-text">内核配置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#基本应用"><span class="nav-number">2.</span> <span class="nav-text">基本应用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#数据结构"><span class="nav-number">3.</span> <span class="nav-text">数据结构</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#task-struct"><span class="nav-number">3.1.</span> <span class="nav-text">task_struct</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#css-set"><span class="nav-number">3.2.</span> <span class="nav-text">css_set</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#cgroup-subsys-state"><span class="nav-number">3.3.</span> <span class="nav-text">cgroup_subsys_state</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#cgroup"><span class="nav-number">3.4.</span> <span class="nav-text">cgroup</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#cg-cgroup-link"><span class="nav-number">3.5.</span> <span class="nav-text">cg_cgroup_link</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#cgroupfs-root"><span class="nav-number">3.6.</span> <span class="nav-text">cgroupfs_root</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#cgroup-subsys"><span class="nav-number">3.7.</span> <span class="nav-text">cgroup_subsys</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#联系"><span class="nav-number">3.8.</span> <span class="nav-text">联系</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#cgroup初始化"><span class="nav-number">4.</span> <span class="nav-text">cgroup初始化</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#cgroup-init-early"><span class="nav-number">4.1.</span> <span class="nav-text">cgroup_init_early</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#cgroup-init"><span class="nav-number">4.2.</span> <span class="nav-text">cgroup_init</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#subsys"><span class="nav-number">4.3.</span> <span class="nav-text">subsys</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#cgroup文件系统的挂载"><span class="nav-number">5.</span> <span class="nav-text">cgroup文件系统的挂载</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#注册："><span class="nav-number">5.1.</span> <span class="nav-text">注册：</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#调用关系："><span class="nav-number">5.2.</span> <span class="nav-text">调用关系：</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#创建子cgroup"><span class="nav-number">6.</span> <span class="nav-text">创建子cgroup</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#task"><span class="nav-number">7.</span> <span class="nav-text">task</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#DEBUG子系统实现"><span class="nav-number">8.</span> <span class="nav-text">DEBUG子系统实现</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#参考"><span class="nav-number">9.</span> <span class="nav-text">参考</span></a></li></ol></div></div><div class="site-overview-wrap sidebar-panel"><div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person"> <img class="site-author-image" itemprop="image" alt="Winddoing" src="/images/Winddoing.jpg"><p class="site-author-name" itemprop="name">Winddoing</p><div class="site-description" itemprop="description">失败缘于忽视细处，成功始于重视小事。</div></div><div class="site-state-wrap motion-element"><nav class="site-state"><div class="site-state-item site-state-posts"> <a href="/archives/"><span class="site-state-item-count">248</span> <span class="site-state-item-name">日志</span></a></div><div class="site-state-item site-state-categories"> <a href="/categories/"><span class="site-state-item-count">57</span> <span class="site-state-item-name">分类</span></a></div><div class="site-state-item site-state-tags"> <a href="/tags/"><span class="site-state-item-count">214</span> <span class="site-state-item-name">标签</span></a></div></nav></div><div class="links-of-author motion-element"><span class="links-of-author-item"><a href="https://github.com/Winddoing" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;Winddoing" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i> GitHub</a></span><span class="links-of-author-item"><a href="https://gitee.com/winddoing" title="Gitee → https:&#x2F;&#x2F;gitee.com&#x2F;winddoing" rel="noopener" target="_blank"><i class="fa fa-fw fa-codiepie"></i> Gitee</a></span><span class="links-of-author-item"><a href="mailto:winddoing@sina.cn" title="E-Mail → mailto:winddoing@sina.cn" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i> E-Mail</a></span><span class="links-of-author-item"><a href="https://stackoverflow.com/users/9567361/winddoing" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;users&#x2F;9567361&#x2F;winddoing" rel="noopener" target="_blank"><i class="fa fa-fw fa-stack-overflow"></i> StackOverflow</a></span><span class="links-of-author-item"><a href="https://travis-ci.org/Winddoing/Winddoing.github.io" title="Travis CI → https:&#x2F;&#x2F;travis-ci.org&#x2F;Winddoing&#x2F;Winddoing.github.io" rel="noopener" target="_blank"><i class="fa fa-fw fa-terminal"></i> Travis CI</a></span></div><div class="cc-license motion-element" itemprop="license"> <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a></div><div class="links-of-blogroll motion-element"><div class="links-of-blogroll-title"><i class="fa fa-fw fa-link"></i> Links</div><ul class="links-of-blogroll-list"><li class="links-of-blogroll-item"> <a href="https://winddoing.gitbooks.io/embedded_notes/content/" title="https:&#x2F;&#x2F;winddoing.gitbooks.io&#x2F;embedded_notes&#x2F;content&#x2F;" rel="noopener" target="_blank">嵌入式相关</a></li><li class="links-of-blogroll-item"> <a href="http://blog.csdn.net/sdreamq" title="http:&#x2F;&#x2F;blog.csdn.net&#x2F;sdreamq" rel="noopener" target="_blank">CSDN</a></li><li class="links-of-blogroll-item"> <a href="http://www.wowotech.net/" title="http:&#x2F;&#x2F;www.wowotech.net&#x2F;" rel="noopener" target="_blank">蜗窝科技</a></li><li class="links-of-blogroll-item"> <a href="https://blog.csdn.net/xiongxianze" title="https:&#x2F;&#x2F;blog.csdn.net&#x2F;xiongxianze" rel="noopener" target="_blank">xiongxianze</a></li></ul></div><div id="days"></div><script>function show_date_time(){window.setTimeout("show_date_time()",1e3),BirthDay=new Date("02/26/2014 15:00:00"),today=new Date,timeold=today.getTime()-BirthDay.getTime(),sectimeold=timeold/1e3,secondsold=Math.floor(sectimeold),msPerDay=864e5,e_daysold=timeold/msPerDay,daysold=Math.floor(e_daysold),e_hrsold=24*(e_daysold-daysold),hrsold=setzero(Math.floor(e_hrsold)),e_minsold=60*(e_hrsold-hrsold),minsold=setzero(Math.floor(60*(e_hrsold-hrsold))),seconds=setzero(Math.floor(60*(e_minsold-minsold))),document.getElementById("days").innerHTML="已运行"+daysold+"天"+hrsold+"小时"+minsold+"分"+seconds+"秒"}function setzero(e){return e<10&&(e="0"+e),e}show_date_time()</script></div></div></aside><div id="sidebar-dimmer"></div></div></main><footer class="footer"><div class="footer-inner"><div class="copyright"> &copy; 2014 – <span itemprop="copyrightYear">2020</span><span class="with-love" id="heart"><i class="fa fa-heartbeat"></i></span> <span class="author" itemprop="copyrightHolder">Winddoing</span> <span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-area-chart"></i></span> <span title="站点总字数">652k</span> <span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-coffee"></i></span> <span title="站点阅读时长">9:53</span></div><div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> 强力驱动 v3.9.0</div> <span class="post-meta-divider">|</span><div class="theme-info">主题 – <a href="https://mist.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Mist</a> v7.7.0</div><div class="busuanzi-count"><script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span class="post-meta-item" id="busuanzi_container_site_uv" style="display:none"><span class="post-meta-item-icon"><i class="fa fa-user"></i></span><span class="site-uv" title="总访客量"><span id="busuanzi_value_site_uv"></span></span></span> <span class="post-meta-divider">|</span><span class="post-meta-item" id="busuanzi_container_site_pv" style="display:none"><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span><span class="site-pv" title="总访问量"><span id="busuanzi_value_site_pv"></span></span></span></div><div style="display:inline"><script type="text/javascript">var cnzz_protocol="https:"==document.location.protocol?" https://":" http://";document.write(unescape("%3Cspan id='cnzz_stat_icon_1254703532'%3E%3C/span%3E%3Cscript src='"+cnzz_protocol+"s95.cnzz.com/z_stat.php%3Fid%3D1254703532%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"))</script></div><script>
  function leancloudSelector(url) {
    url = encodeURI(url);
    return document.getElementById(url).querySelector('.leancloud-visitors-count');
  }
  if (CONFIG.page.isPost) {
    function addCount(Counter) {
      var visitors = document.querySelector('.leancloud_visitors');
      var url = decodeURI(visitors.getAttribute('id'));
      var title = visitors.getAttribute('data-flag-title');

      Counter('get', `/classes/Counter?where=${JSON.stringify({ url })}`)
        .then(response => response.json())
        .then(({ results }) => {
          if (results.length > 0) {
            var counter = results[0];
            Counter('put', '/classes/Counter/' + counter.objectId, { time: { '__op': 'Increment', 'amount': 1 } })
              .then(response => response.json())
              .then(() => {
                leancloudSelector(url).innerText = counter.time + 1;
              })
              .catch(error => {
                console.error('Failed to save visitor count', error);
              })
          } else {
              Counter('post', '/classes/Counter', { title: title, url: url, time: 1 })
                .then(response => response.json())
                .then(() => {
                  leancloudSelector(url).innerText = 1;
                })
                .catch(error => {
                  console.error('Failed to create', error);
                });
          }
        })
        .catch(error => {
          console.error('LeanCloud Counter Error', error);
        });
    }
  } else {
    function showTime(Counter) {
      var visitors = document.querySelectorAll('.leancloud_visitors');
      var entries = [...visitors].map(element => {
        return decodeURI(element.getAttribute('id'));
      });

      Counter('get', `/classes/Counter?where=${JSON.stringify({ url: { '$in': entries } })}`)
        .then(response => response.json())
        .then(({ results }) => {
          if (results.length === 0) {
            document.querySelectorAll('.leancloud_visitors .leancloud-visitors-count').forEach(element => {
              element.innerText = 0;
            });
            return;
          }
          for (let item of results) {
            let { url, time } = item;
            leancloudSelector(url).innerText = time;
          }
          for (let url of entries) {
            var element = leancloudSelector(url);
            if (element.innerText == '') {
              element.innerText = 0;
            }
          }
        })
        .catch(error => {
          console.error('LeanCloud Counter Error', error);
        });
    }
  }

  fetch('https://app-router.leancloud.cn/2/route?appId=Q8qpjA3fOO7FEUBqcmcQFptF-gzGzoHsz')
    .then(response => response.json())
    .then(({ api_server }) => {
      var Counter = (method, url, data) => {
        return fetch(`https://${api_server}/1.1${url}`, {
          method: method,
          headers: {
            'X-LC-Id': 'Q8qpjA3fOO7FEUBqcmcQFptF-gzGzoHsz',
            'X-LC-Key': 'tgUTq5bX3fVmn916EMRe65eJ',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data)
        });
      };
      if (CONFIG.page.isPost) {
        if (CONFIG.hostname !== location.hostname) return;
        addCount(Counter);
      } else if (document.querySelectorAll('.post-title-link').length >= 1) {
        showTime(Counter);
      }
    });
  </script></div></footer></div><script src="/lib/anime.min.js"></script><script src="/lib/velocity/velocity.min.js"></script><script src="/lib/velocity/velocity.ui.min.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script><script>!function(){var t=document.createElement("script"),e=window.location.protocol.split(":")[0];t.src="https"===e?"https://zz.bdstatic.com/linksubmit/push.js":"http://push.zhanzhang.baidu.com/push.js";var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}()</script><script src="/js/local-search.js"></script><script>
if (document.querySelectorAll('pre.mermaid').length) {
  NexT.utils.getScript('//cdn.jsdelivr.net/npm/mermaid@8/dist/mermaid.min.js', () => {
    mermaid.initialize({
      theme: 'forest',
      logLevel: 3,
      flowchart: { curve: 'linear' },
      gantt: { axisFormat: '%m/%d/%Y' },
      sequence: { actorMargin: 50 }
    });
  }, window.mermaid);
}
</script><script src="//cdn.jsdelivr.net/gh/theme-next/theme-next-needmoreshare2@1/needsharebutton.min.js"></script><script>pbOptions={iconStyle:"default",boxForm:"horizontal",position:"bottomCenter",networks:"Weibo,Wechat,QQZone,Twitter,Facebook,Evernote"},new needShareButton("#needsharebutton-postbottom",pbOptions)</script><script>
NexT.utils.loadComments(document.querySelector('#lv-container'), () => {
  window.livereOptions = {
    refer: location.pathname.replace(CONFIG.root, '').replace('index.html', '')
  };
  (function(d, s) {
    var j, e = d.getElementsByTagName(s)[0];
    if (typeof LivereTower === 'function') { return; }
    j = d.createElement(s);
    j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
    j.async = true;
    e.parentNode.insertBefore(j, e);
  })(document, 'script');
});
</script></body></html>